﻿using System.Collections.Generic;
using System.Windows.Input;
using TestBat.IModels.Domain;
using TestBat.IModels.Models;
using TestBat.IViewModels.Factories;
using TestBat.IViewModels.Workspaces.Schedules;
using TestBat.IViewModels.Workspaces.Tasks;
using TestBat.IViewModels.Workspaces.Trainees;
using TestBat.ServiceLocator;
using TestBat.ViewModels.Attributes;
using TestBat.ViewModels.Base;
using TestBat.ViewModels.Base.Commands;
using TestBat.ViewModels.Workspaces.Trainees;

namespace TestBat.ViewModels.Workspaces.Schedules
{
    public class ScheduleViewModel : ListItemViewModel, IScheduleViewModel
    {
        public ScheduleViewModel(ISchedule schedule, IScheduleModel scheduleModel, ITaskFolderModel taskFolderModel,
            ITaskTreeViewModelFactory taskTreeViewModelFactory, IScheduleTasksViewModelFactory scheduleTasksViewModelFactory)
        {
            this.schedule = schedule;
            this.scheduleModel = scheduleModel;
            this.taskFolderModel = taskFolderModel;
            this.taskTreeViewModelFactory = taskTreeViewModelFactory;
            this.scheduleTasksViewModelFactory = scheduleTasksViewModelFactory;
            this.traineeGroupList = null;
            this.scheduleTaskList = null;
            this.scheduleTraineeGroupList = null;
        }

        public ICommand SaveCommand
        {
            get
            {
                return new RelayCommand(ctx => Save());
            }
        }

        public ICommand AddScheduleTasksCommand
        {
            get
            {
                return new RelayCommand(
                    ctx => AddScheduleTasks(),
                    ctx => TaskTree.SelectedItem != null);
            }
        }

        public ICommand RemoveScheduleTaskCommand
        {
            get
            {
                return new RelayCommand(
                    ctx => RemoveScheduleTask(),
                    ctx => ScheduleTaskList.Selected != null);
            }
        }

        public ICommand MoveScheduleTaskUpCommand
        {
            get
            {
                return new RelayCommand(
                    ctx => MoveScheduleTaskUp(),
                    ctx => ScheduleTaskList.Selected != null);
            }
        }

        public ICommand MoveScheduleTaskDownCommand
        {
            get
            {
                return new RelayCommand(
                    ctx => MoveScheduleTaskDown(),
                    ctx => ScheduleTaskList.Selected != null);
            }
        }

        public ICommand AddScheduleTraineeGroupCommand
        {
            get
            {
                return new RelayCommand(
                    ctx => AddScheduleTraineeGroup(),
                    ctx => TraineeGroupList.Selected != null);
            }
        }

        public ICommand RemoveScheduleTraineeGroupCommand
        {
            get
            {
                return new RelayCommand(
                    ctx => RemoveScheduleTraineeGroup(),
                    ctx => ScheduleTraineeGroupList.Selected != null);
            }
        }

        [BusinessErrorDialog]
        private void MoveScheduleTaskUp()
        {
            var selected = ScheduleTaskList.Selected.ScheduleTask;

            scheduleModel.MoveScheduleTaskUp(Schedule, selected);

            // recreate view model list, keeping selection
            ScheduleTaskList.RecreateItems();
        }

        [BusinessErrorDialog]
        private void MoveScheduleTaskDown()
        {
            var selected = ScheduleTaskList.Selected.ScheduleTask;

            scheduleModel.MoveScheduleTaskDown(Schedule, selected);

            // recreate view model list, keeping selection
            ScheduleTaskList.RecreateItems();
        }

        [BusinessErrorDialog]
        private void RemoveScheduleTask()
        {
            // remove from model
            scheduleModel.RemoveScheduleTask(Schedule, scheduleTaskList.Selected.ScheduleTask);

            // recreate view model list, selecting nothing
            ScheduleTaskList.RecreateItems();
        }

        [BusinessErrorDialog]
        private void AddScheduleTasks()
        {
            var itemVM = TaskTree.SelectedItem;

            if (itemVM is ITaskViewModel)
            { // add task
                var after = (ScheduleTaskList.Selected != null) ? scheduleTaskList.Selected.ScheduleTask : null;

                // add to model
                IScheduleTask item = scheduleModel.AddScheduleTask(Schedule, (itemVM as ITaskViewModel).Task, after);

                // recreate view model list, keeping selection
                ScheduleTaskList.RecreateItems();
            }
            else if (itemVM is ITaskFolderViewModel)
            { // add task folder
                var after = (ScheduleTaskList.Selected != null) ? scheduleTaskList.Selected.ScheduleTask : null;

                IList<ITask> tasks = taskFolderModel.GetTasks((itemVM as ITaskFolderViewModel).TaskFolder);
                IList<IScheduleTask> items = scheduleModel.AddScheduleTasks(Schedule, tasks, after);

                // recreate view model list, keeping selection
                ScheduleTaskList.RecreateItems();
            }
        }

        [BusinessErrorDialog]
        private void AddScheduleTraineeGroup()
        {
            var itemVM = TraineeGroupList.Selected;

            scheduleModel.AddScheduleTraineeGroup(schedule, itemVM.TraineeGroup);

            ScheduleTraineeGroupList.RecreateItems();
        }

        [BusinessErrorDialog]
        private void RemoveScheduleTraineeGroup()
        {
            var itemVM = ScheduleTraineeGroupList.Selected;

            scheduleModel.RemoveScheduleTraineeGroup(schedule, itemVM.ScheduleTraineeGroup);

            ScheduleTraineeGroupList.RecreateItems();
        }

        [BusinessErrorDialog]
        [ValidationErrorDialog]
        private void Save()
        {
            scheduleModel.Save(schedule);
        }

        public ISchedule Schedule
        {
            get { return schedule; }
        }

        public ITaskTreeViewModel TaskTree
        {
            get
            {
                if (taskTree == null)
                    taskTree = taskTreeViewModelFactory.Create(true);
                return taskTree;
            }
        }

        public ITraineeGroupListViewModel TraineeGroupList
        {
            get
            {
                if (traineeGroupList == null)
                    traineeGroupList = new TraineeGroupListViewModel(DefaultServiceLocator.Get<ITraineeGroupModel>(), DefaultServiceLocator.Get<ITraineeGroupViewModelFactory>(), false); // TODO: use DI
                return traineeGroupList;
            }
        }

        

        public IScheduleTaskListViewModel ScheduleTaskList
        {
            get
            {
                if (scheduleTaskList == null)
                    scheduleTaskList = scheduleTasksViewModelFactory.Create(schedule); 
                
                return scheduleTaskList;
            }
        }

        public IScheduleTraineeGroupListViewModel ScheduleTraineeGroupList
        {
            get
            {
                if (scheduleTraineeGroupList == null)
                    scheduleTraineeGroupList = new ScheduleTraineeGroupListViewModel(schedule, DefaultServiceLocator.Get<IScheduleModel>());

                return scheduleTraineeGroupList;
            }
        }

        [BusinessErrorDialog]
        public override void OnLostFocus()
        {
            // revert changes
            scheduleModel.Revert(schedule);

            // recreate schedule-items
            ScheduleTaskList.RecreateItems();
            ScheduleTraineeGroupList.RecreateItems();
        }

        private readonly ISchedule schedule;
        private readonly IScheduleModel scheduleModel;
        private readonly ITaskFolderModel taskFolderModel;
        private readonly ITaskTreeViewModelFactory taskTreeViewModelFactory;
        private readonly IScheduleTasksViewModelFactory scheduleTasksViewModelFactory;
        private ITaskTreeViewModel taskTree;
        private ITraineeGroupListViewModel traineeGroupList;
        private IScheduleTaskListViewModel scheduleTaskList;
        private IScheduleTraineeGroupListViewModel scheduleTraineeGroupList;
    }
}
